package com.xtwy.interceptor;

import com.xtwy.entity.Menu;
import com.xtwy.entity.Role;
import com.xtwy.service.MenuService;
import com.xtwy.service.RoleService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.*;


/**
 * @作 者: 侯建军
 * @日 期: 2018/7/29 12:39
 * @描 述: 资源数据定义类
 * @公 司：山西迅腾伟业
 */
@Log
@Service
public class InvocationSecurityMetadataSourceService implements
        FilterInvocationSecurityMetadataSource {
    /**
     * 角色与权限对象
     */
    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuService menuService;
    /**
     * 用来存储配置
     */
    private HashMap<String, Collection<ConfigAttribute>> map = null;

    /**
     * 加载资源，初始化资源变量
     */
    public void loadResourceDefine() {
        map = new HashMap<>();
        Collection<ConfigAttribute> array;
        ConfigAttribute cfg;
        /**
         * 查询所有菜单数据
         * findByRoleId
         */
        List<Role> roles = roleService.findAllRoles();
        List<Menu> menus = null;
        for (Role role : roles) {
            //根据角色id获取权限
            menus = menuService.getMenus(role.getId());

            for (Menu menu : menus) {
                array = new ArrayList<>();
                cfg = new SecurityConfig(role.getValue());
                array.add(cfg);
                map.put(menu.getUrl(), array);
//                Collection<ConfigAttribute> configAttributes = null;
                //将角色名放入配置信息中 例：ROLE_ADMIN
//                ConfigAttribute configAttribute = new SecurityConfig(role.getValue());
//                if (map.containsKey(menu.getUrl())) {
//                    configAttributes = map.get(menu.getUrl());
//                    configAttributes.add(configAttribute);
//                } else {
//                    configAttributes = new ArrayList<ConfigAttribute>();
//                    configAttributes.add(configAttribute);
//                }
//                //排除除空路径
//                if (menu.getUrl().isEmpty()) {
//                    continue;
//                }
//                array = new ArrayList<>();
                //获取菜单名，加入到安全配置
//                cfg = new SecurityConfig(menu.getName());
                log.warning(role.getValue() + "获取菜单名称");
                //此处只添加了用户的名字，其实还可以添加更多权限的信息，例如请求方法到ConfigAttribute的集合中去。
                // 此处添加的信息将会作为AccessDecisionManager类的decide的第三个参数。
//                array.add(cfg);
                log.warning(menu.getUrl() + "获取菜单地址");
                //用权限的getUrl() 作为map的key，用ConfigAttribute的集合作为 value，
//                map.put(menu.getUrl(), configAttributes);
            }
        }
    }

//    AntPathMatcher urlMatcher = new AntPathMatcher();
    /*
     * 根据请求的资源地址，获取它所拥有的权限
     * 返回请求的资源需要的权限
     * url通配符为两颗星，比如说 /user下的所有url，应该写成 /user/**;
     * 权限的名字可以随意起名
     */

    //此方法是为了判定用户请求的url 是否在权限表中，如果在权限表中，则返回给 decide 方法，用来判定用户是否有此权限。如果不在权限表中则放行。
    //因为我不想每一次来了请求，都先要匹配一下权限表中的信息是不是包含此url，
    // 我准备直接拦截，不管请求的url 是什么都直接拦截，然后在MyAccessDecisionManager的decide 方法中做拦截还是放行的决策。
    //所以此方法的返回值不能返回 null 此处我就随便返回一下。
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        Collection<ConfigAttribute> co=new ArrayList<>();
        co.add(new SecurityConfig("null"));
        return co;
    }

//        //object 中包含用户请求的request 信息
//        String resUrl;
//
//        Collection<ConfigAttribute> urlSet = new HashSet<ConfigAttribute>();
//
//        Iterator<String> iter = map.keySet().iterator();
////        log.warning(map.toString());
//        //获取请求信息
//        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
//        //获取请求的url方法
//        String url = ((FilterInvocation) object).getRequestUrl();
//        if (url.indexOf("&") != -1) {
//            url = url.substring(0, url.indexOf("&"));
//        }
//        //获取请求的url资源
//        String methodUrl = "";
//        if (url.indexOf("?") != -1) {
//            methodUrl = url.substring(0, url.indexOf("?"));
//        }
//
//        log.warning(url + "请求的url");
//        //url验证
//        AntPathRequestMatcher matcher;
//        log.warning(map.size()+"");
//        while (iter.hasNext()) {
//            resUrl = iter.next();
//            matcher = new AntPathRequestMatcher(resUrl);
//            log.warning(url + ":" + resUrl);
//            log.warning(urlMatcher.match(url, resUrl) + "");
            //如果该拥有url资源
//            if (!"".equals(methodUrl) && urlMatcher.match(methodUrl, resUrl)) {
//                Iterator<ConfigAttribute> urlIt = map.get(resUrl).iterator();
//                while (urlIt.hasNext()) {
//                    urlSet.add(urlIt.next());
//                }
//                //如果拥有方法资源
//            } else if (urlMatcher.match(url, resUrl)) {
//                Iterator<ConfigAttribute> urlIt = map.get(resUrl).iterator();
//                while (urlIt.hasNext()) {
//                    urlSet.add(urlIt.next());
//                }
//            }


//            log.warning(resUrl + "请求地址"+matcher.matches(request));
//            if (matcher.matches(request)) {
//                return map.get(resUrl);
//            }
//        }
//        log.warning(map.toString());
        //返回所有的角色
//        if (urlSet != null && urlSet.size() > 0) {
//            return urlSet;
//        }
//        return null;
//    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
